/**********************************************************************************************************
** 驱动文件：	ups-AF9300.c
** 驱动类型：	ups
** 设备名称：	UPS监测
** 设备型号：	AF9300
** 设备品牌：	艾福瑞斯
** 设备协议：	RS232 UPS Communication Protocol
** 驱动描述：	适用于AF9300系列三进单出高频在线式UPS
** 生成日期：	2019-08-09 21:43:56
**********************************************************************************************************/
#include "Includes.h"


/**********************************************************************************************************
* 定义设备数据点变量结构
**********************************************************************************************************/
typedef struct{
	Var InputVoltage;							//输入电压
	Var InputFrequency;							//输入频率
	Var OutputVoltage;							//输出电压
	Var OutputFrequency;						//输出频率
	Var OutputCurrent;							//输出电流
	Var OutputLoadPercent;						//输出负载率
	Var PositiveBUSVoltage;						//正母线电压
	Var NegativeBUSVoltage;						//负母线电压
	Var PositiveBatteryVoltage;					//正电池电压
	Var NegativeBatteryVoltage;					//负电池电压
	Var MaxTemperature;							//最高温度
	Var UPSType;								//UPS类型
	Var UtilityFail;							//市电故障
	Var BatteryLow;								//电池低压
	Var BypassActive;							//旁路激活
	Var UPSFailed;								//UPS故障
	Var EPO;									//紧急停机
	Var TestInProgress;							//UPS测试
	Var ShutdownActive;							//UPS关机
	Var UPSMode;								//运行模式
	Var BatteryVoltage;							//电池电压
	Var BatteryCapacity;						//电池容量
	Var BatteryRemainTime;						//电池剩余时间
	Var InputVoltageUA;							//A相输入电压
	Var InputVoltageUB;							//B相输入电压
	Var InputVoltageUC;							//C相输入电压
}Data_Struct;									//定义变量结构


/**********************************************************************************************************
* 设备数据点变量属性声明
**********************************************************************************************************/
const static Var_Property_Def var_attr[] = {
	{
		FLOAT,
		0,
		READONLY,
		"InputVoltage",
		"输入电压",
		"V",
		"输入电压",
		0,
		0,
		"输入电压过高",
		"输入电压过低",
		0.000,
		0.000
	},
	{
		FLOAT,
		0,
		READONLY,
		"InputFrequency",
		"输入频率",
		"Hz",
		"输入频率",
		0,
		0,
		"输入频率过高",
		"输入频率过低",
		0.000,
		0.000
	},
	{
		FLOAT,
		0,
		READONLY,
		"OutputVoltage",
		"输出电压",
		"V",
		"输出电压",
		0,
		0,
		"输出电压过高",
		"输出电压过低",
		0.000,
		0.000
	},
	{
		FLOAT,
		0,
		READONLY,
		"OutputFrequency",
		"输出频率",
		"Hz",
		"输出频率",
		0,
		0,
		"输出频率过高",
		"输出频率过低",
		0.000,
		0.000
	},
	{
		FLOAT,
		0,
		READONLY,
		"OutputCurrent",
		"输出电流",
		"A",
		"输出电流",
		0,
		0,
		"输出电流过高",
		"输出电流过低",
		0.000,
		0.000
	},
	{
		INTEGER,
		0,
		READONLY,
		"OutputLoadPercent",
		"输出负载率",
		"%",
		"输出负载率",
		0,
		0,
		"输出负载率过高",
		"输出负载率过低",
		0.000,
		0.000
	},
	{
		FLOAT,
		0,
		READONLY,
		"PositiveBUSVoltage",
		"正母线电压",
		"V",
		"正母线电压",
		0,
		0,
		"正母线电压过高",
		"正母线电压过低",
		0.000,
		0.000
	},
	{
		FLOAT,
		0,
		READONLY,
		"NegativeBUSVoltage",
		"负母线电压",
		"V",
		"负母线电压",
		0,
		0,
		"负母线电压过高",
		"负母线电压过低",
		0.000,
		0.000
	},
	{
		FLOAT,
		0,
		READONLY,
		"PositiveBatteryVoltage",
		"正电池电压",
		"V",
		"正电池电压",
		0,
		0,
		"正电池电压过高",
		"正电池电压过低",
		0.000,
		0.000
	},
	{
		FLOAT,
		0,
		READONLY,
		"NegativeBatteryVoltage",
		"负电池电压",
		"V",
		"负电池电压",
		0,
		0,
		"负电池电压过高",
		"负电池电压过低",
		0.000,
		0.000
	},
	{
		FLOAT,
		0,
		READONLY,
		"MaxTemperature",
		"最高温度",
		"℃",
		"最高温度",
		0,
		0,
		"最高温度过高",
		"最高温度过低",
		0.000,
		0.000
	},
	{
		OCTSTR,
		0,
		READONLY,
		"UPSType",
		"UPS类型",
		"",
		"UPS类型：0-后备式；1-在线互动式；2-在线式",
		0,
		0,
		"",
		"",
		0.000,
		0.000
	},
	{
		OCTSTR,
		0,
		READONLY,
		"UtilityFail",
		"市电故障",
		"",
		"市电故障：0-正常；1-故障",
		0,
		0,
		"故障",
		"",
		0.000,
		0.000
	},
	{
		OCTSTR,
		0,
		READONLY,
		"BatteryLow",
		"电池低压",
		"",
		"电池低压：0-正常；1-低压",
		0,
		0,
		"低压",
		"",
		0.000,
		0.000
	},
	{
		OCTSTR,
		0,
		READONLY,
		"BypassActive",
		"旁路激活",
		"",
		"旁路激活：0-未激活；1-激活",
		0,
		0,
		"激活",
		"",
		0.000,
		0.000
	},
	{
		OCTSTR,
		0,
		READONLY,
		"UPSFailed",
		"UPS故障",
		"",
		"UPS故障：0-正常；1-故障",
		0,
		0,
		"故障",
		"",
		0.000,
		0.000
	},
	{
		OCTSTR,
		0,
		READONLY,
		"EPO",
		"紧急停机",
		"",
		"紧急停机：0-未发生；1-发生",
		0,
		0,
		"紧急停机",
		"",
		0.000,
		0.000
	},
	{
		OCTSTR,
		0,
		READONLY,
		"TestInProgress",
		"UPS测试",
		"",
		"UPS测试：0-未测试；1-测试中",
		0,
		0,
		"",
		"",
		0.000,
		0.000
	},
	{
		OCTSTR,
		0,
		READONLY,
		"ShutdownActive",
		"UPS关机",
		"",
		"UPS关机：0-未关机；1-关机激活",
		0,
		0,
		"关机激活",
		"",
		0.000,
		0.000
	},
	{
		OCTSTR,
		0,
		READONLY,
		"UPSMode",
		"运行模式",
		"",
		"UPS运行模式：0-上电初始、1-待机模式、2-旁路模式、3-在线模式、4-电池模式、5-电池测试、6-故障模式、7-高效模式、8-互动模式、9-关机模式",
		0,
		0,
		"",
		"",
		0.000,
		0.000
	},
	{
		FLOAT,
		0,
		READONLY,
		"BatteryVoltage",
		"电池电压",
		"V",
		"电池电压",
		0,
		0,
		"电池电压过高",
		"电池电压过低",
		0.000,
		0.000
	},
	{
		INTEGER,
		0,
		READONLY,
		"BatteryCapacity",
		"电池容量",
		"%",
		"电池容量",
		0,
		0,
		"电池容量过高",
		"电池容量过低",
		0.000,
		0.000
	},
	{
		INTEGER,
		0,
		READONLY,
		"BatteryRemainTime",
		"电池剩余时间",
		"分",
		"电池剩余时间",
		0,
		0,
		"电池剩余时间过高",
		"电池剩余时间过低",
		0.000,
		0.000
	},
	{
		FLOAT,
		0,
		READONLY,
		"InputVoltageUA",
		"A相输入电压",
		"V",
		"A相输入电压",
		0,
		0,
		"A相输入电压过高",
		"A相输入电压过低",
		0.000,
		0.000
	},
	{
		FLOAT,
		0,
		READONLY,
		"InputVoltageUB",
		"B相输入电压",
		"V",
		"B相输入电压",
		0,
		0,
		"B相输入电压过高",
		"B相输入电压过低",
		0.000,
		0.000
	},
	{
		FLOAT,
		0,
		READONLY,
		"InputVoltageUC",
		"C相输入电压",
		"V",
		"C相输入电压",
		0,
		0,
		"C相输入电压过高",
		"C相输入电压过低",
		0.000,
		0.000
	}
};


/**********************************************************************************************************
* 函数名称： static void cmd_fun(short index, int addr, void *data, char *cmd, short *len)
* 函数说明： 生成获取传感器数据指令
* 输入参数： 指令索引，传感器地址，变量结构体指针,以及指令缓存区指针,指令长度
* 返回参数： 无
**********************************************************************************************************/
static void cmd_fun(short index, int addr, void *data, char *cmd, short *len)
{
	switch(index)
	{
		case 0:
		case 1:
			*len = sprintf(cmd,"QGS\r");
			break;		
		case 2:
			*len = sprintf(cmd,"QMOD\r");
			break;
		case 3:
			*len = sprintf(cmd,"QBV\r");
			break;	
		case 4:
			*len = sprintf(cmd,"Q3PV\r");
			break;				
		default:
			break;
	}
}


/**********************************************************************************************************
* 函数名称： static int parse_fun(short index, int addr, void *data, char *buf, short len)
* 函数说明： 解析传感器响应的数据，并写入数据库
* 输入参数： 解析索引,传感器地址，变量结构体指针，以及响应数据缓存取指针，响应数据长度
* 返回参数： 返回解析结果，返回0成功，返回1失败
**********************************************************************************************************/
static int parse_fun(short index, int addr, void *data, char *buf, short len)
{
	const char		*UPSModel[10][2] = {{"P","上电初始"},{"S","待机模式"},{"Y","旁路模式"},{"L","在线模式"},{"B","电池模式"},{"T","电池测试"},{"F","故障模式"},{"E","高效模式"},{"C","互动模式"},{"D","关机模式"}};

	Data_Struct 	*d = (Data_Struct*)data;
	int				i;
	
	if(buf!=NULL && buf[0]=='(' && len>0 && buf[len-1]=='\r')
	{
		switch(index)
		{
			case 0:
				break;
			case 1:				
				d->InputVoltage.value.fnum				= atof(buf+1);
				d->InputFrequency.value.fnum			= atof(buf+7);
				d->OutputVoltage.value.fnum				= atof(buf+12);
				d->OutputFrequency.value.fnum			= atof(buf+18);
				d->OutputCurrent.value.fnum				= atof(buf+23);
				d->OutputLoadPercent.value.inum			= atoi(buf+29);
				d->PositiveBUSVoltage.value.fnum		= atof(buf+33);
				d->NegativeBUSVoltage.value.fnum		= atof(buf+39);
				d->PositiveBatteryVoltage.value.fnum	= atof(buf+45);
				d->NegativeBatteryVoltage.value.fnum 	= atof(buf+51);
				d->MaxTemperature.value.fnum			= atof(buf+57);
				
				if(buf[63]=='0'&&buf[64]=='0'){
					d->UPSType.value.str = "后备式";
				}
				else if(buf[63]=='0'&&buf[64]=='1'){
					d->UPSType.value.str = "在线互动式";
				}
				else if(buf[63]=='1'&&buf[64]=='0'){
					d->UPSType.value.str = "在线式";
				}

				d->UtilityFail.value.str				= buf[65]=='1'?"故障":"正常";
				Set_Var_Status(&d->UtilityFail,			  buf[65]=='1'?Alarm:Normal, NULL);
				d->BatteryLow.value.str					= buf[66]=='1'?"低压":"正常";
				Set_Var_Status(&d->BatteryLow,			  buf[66]=='1'?Alarm:Normal, NULL);
				d->BypassActive.value.str				= buf[67]=='1'?"激活":"未激活";
				Set_Var_Status(&d->BypassActive,		  buf[67]=='1'?Alarm:Normal, NULL);
				d->UPSFailed.value.str					= buf[68]=='1'?"故障":"正常";
				Set_Var_Status(&d->UPSFailed,			  buf[68]=='1'?Alarm:Normal, NULL);
				d->EPO.value.str						= buf[69]=='1'?"发生":"未发生";
				Set_Var_Status(&d->EPO,					  buf[69]=='1'?Alarm:Normal, NULL);
				d->TestInProgress.value.str				= buf[70]=='1'?"测试中":"未测试";
				Set_Var_Status(&d->TestInProgress,		  buf[70]=='1'?Alarm:Normal, NULL);
				d->ShutdownActive.value.str				= buf[71]=='1'?"关机激活":"未关机";
				Set_Var_Status(&d->ShutdownActive,		  buf[71]=='1'?Alarm:Normal, NULL);
				break;
			case 2:
				for(i=0; i<10; i++){
					if(*UPSModel[i][0]==buf[1]){
						d->UPSMode.value.str			= UPSModel[i][1];
						Set_Var_Status(&d->UPSMode,		i==6?Alarm:Normal, NULL);	
						break;
					}
				}
				break;
			case 3:
				d->BatteryVoltage.value.fnum			= atof(buf+1);
				d->BatteryCapacity.value.inum			= atoi(buf+13);
				d->BatteryRemainTime.value.inum		 	= atoi(buf+17);
				break;
			case 4:
				d->InputVoltageUA.value.fnum			= atof(buf+1);
				d->InputVoltageUB.value.fnum			= atof(buf+7);
				d->InputVoltageUC.value.fnum		 	= atof(buf+13);				
				break;
			default:
				break;
		}
		return 0;
	}
	return 1;
}


/**********************************************************************************************************
* 函数名称： void ups_AF9300_Registration(void)
* 函数说明： UPS监测驱动注册
* 输入参数： 无
* 返回参数： 无
**********************************************************************************************************/
void ups_AF9300_Registration(void)
{
	DeviceDriverRegistration(
		"ups",													//设备类型
		"UPS监测",												//设备名称（导航栏默认显示名称）
		"山特",													//设备品牌		
		"AF9300",												//设备型号
		"适用于AF9300系列三进单出高频在线式UPS",				//驱动描述
		var_attr,												//变量属性声明
		sizeof(Data_Struct),									//变量结构体空间大小
		cmd_fun,												//发送指令生成函数
		parse_fun,												//数据解析函数
		1000													//设备响应超时时间
	);
	
#if 0
	#define CMD1 "QGS\r"
	#define RSP1 "(220.2 50.0 220.0 50.0 027.0 100 345.8 344.9 241.0 241.5 045.0 100011000000\r"	
	#define CMD2 "QMOD\r"
	#define RSP2 "(Y\r"		
	#define CMD3 "QBV\r"
	#define RSP3 "(345.8 02 02 089 999\r"		
	#define CMD4 "Q3PV\r"
	#define RSP4 "(220.2 215.3 222.1 381.4 373.2 384.6\r"		
	VirtualFrameRegistration(CMD1, sizeof(CMD1)-1, RSP1, sizeof(RSP1)-1);		
	VirtualFrameRegistration(CMD2, sizeof(CMD2)-1, RSP2, sizeof(RSP2)-1);		
	VirtualFrameRegistration(CMD3, sizeof(CMD3)-1, RSP3, sizeof(RSP3)-1);	
	VirtualFrameRegistration(CMD4, sizeof(CMD4)-1, RSP4, sizeof(RSP4)-1);		
#endif	
}

